<template>
  <el-dialog
    :model-value="visible"
    class="defect-detail-dialog"
    width="1400px"
    align-center
    :close-on-click-modal="false"
    :before-close="handleClose"
    @update:model-value="(value: boolean) => emit('update:visible', value)"
  >
    <div class="defect-detail" v-if="localDefect">
      <div class="detail-body">
        <div class="primary-column">
          <div class="detail-header">
            <div class="header-top">
              <span v-if="localDefect?.id" class="detail-id">ID {{ localDefect.id }}</span>
              <div class="status-tags">
                <el-tag
                  v-if="localDefect?.status"
                  :type="getStatusType(localDefect.status)"
                  size="small"
                >
                  {{ getStatusText(localDefect.status) }}
                </el-tag>
                <el-tag
                  v-if="localDefect?.priority"
                  :type="getPriorityType(localDefect.priority)"
                  size="small"
                >
                  {{ getPriorityText(localDefect.priority) }}
                </el-tag>
                <el-tag
                  v-if="localDefect?.severity"
                  :type="getSeverityType(localDefect.severity)"
                  size="small"
                >
                  {{ getSeverityText(localDefect.severity) }}
                </el-tag>
                <el-tag v-if="localDefect?.type" size="small" type="info">
                  {{ getTypeText(localDefect.type) }}
                </el-tag>
                <el-tag v-if="localDefect?.source" size="small" type="warning">
                  {{ getSourceText(localDefect.source) }}
                </el-tag>
              </div>
            </div>

            <div class="title-section">
              <div class="field-label">
                <span>缺陷标题</span>
                <span class="required">*</span>
              </div>
              <el-input
                v-model="localDefect.title"
                placeholder="请输入缺陷标题"
                maxlength="200"
                show-word-limit
                size="large"
                class="title-input"
                :class="{ 'field-error': fieldErrors.title }"
                @blur="handleSaveField('title')"
                @input="clearFieldError('title')"
              />
              <div v-if="fieldErrors.title" class="error-message">{{ fieldErrors.title }}</div>
            </div>

            <div class="header-meta">
              <span v-if="localDefect.project_id && localDefect.project_name" class="project-info">
                项目：<el-link type="primary" :underline="false">{{ localDefect.project_name }}</el-link>
              </span>
              <span v-if="localDefect.requirement_id && localDefect.requirement_name" class="requirement-info">
                关联需求：<el-link type="primary" :underline="false">{{ localDefect.requirement_name }}</el-link>
              </span>
              <span class="meta-user-item">
                <span class="meta-label">创建人：</span>
                <UserAvatar
                  v-if="localDefect.reporter_id"
                  :user="getUserById(localDefect.reporter_id)"
                  size="small"
                  circle
                />
                <span>{{ localDefect.reporter_name || '未指定' }}</span>
              </span>
              <span class="meta-user-item">
                <span class="meta-label">负责人：</span>
                <UserAvatar
                  v-if="localDefect.assignee_id"
                  :user="getUserById(localDefect.assignee_id)"
                  size="small"
                  circle
                />
                <span>{{ localDefect.assignee_name || '未分配' }}</span>
              </span>
              <span v-if="localDefect.verifier_name" class="meta-user-item verifier-info">
                <span class="meta-label">验证人：</span>
                <UserAvatar
                  v-if="localDefect.verifier_id"
                  :user="getUserById(localDefect.verifier_id)"
                  size="small"
                  circle
                />
                <span>{{ localDefect.verifier_name }}</span>
              </span>
              <span v-if="localDefect.created_at">创建时间：{{ formatDateTimeDisplay(localDefect.created_at) }}</span>
              <span v-if="localDefect.updated_at">更新时间：{{ formatDateTimeDisplay(localDefect.updated_at) }}</span>
            </div>
          </div>

          <!-- 主要内容区域 - 合并的文本内容区域 -->
          <section class="section-card content-section">
            <div class="content-header">
              <div class="content-title">缺陷详情</div>
              <div class="content-actions">
                <template v-if="!editingContent">
                  <el-button
                    size="small"
                    type="primary"
                    @click="editingContent = true"
                  >
                    编辑
                  </el-button>
                </template>
                <template v-else>
                  <el-button
                    size="small"
                    @click="cancelEditContent"
                  >
                    取消
                  </el-button>
                  <el-button
                    size="small"
                    type="primary"
                    :loading="savingContent"
                    @click="saveContent"
                  >
                    保存
                  </el-button>
                </template>
              </div>
            </div>
            <div class="content-scrollable">
              <div v-if="editingContent" class="content-editor">
                <EnhancedRichTextEditor
                  v-model="combinedContent"
                  placeholder="请输入缺陷详情内容..."
                  :min-height="400"
                />
              </div>
              <div v-else class="content-display">
                <div v-if="hasContent(localDefect.description)" class="content-display-item">
                  <div class="content-display-label">缺陷描述</div>
                  <div class="text-content" v-html="localDefect.description"></div>
                </div>
                <div v-if="hasContent(localDefect.steps_to_reproduce)" class="content-display-item">
                  <div class="content-display-label">复现步骤</div>
                  <div class="text-content" v-html="localDefect.steps_to_reproduce"></div>
                </div>
                <div v-if="hasContent(localDefect.expected_result)" class="content-display-item">
                  <div class="content-display-label">期望结果</div>
                  <div class="text-content" v-html="localDefect.expected_result"></div>
                </div>
                <div v-if="hasContent(localDefect.actual_result)" class="content-display-item">
                  <div class="content-display-label">实际结果</div>
                  <div class="text-content" v-html="localDefect.actual_result"></div>
                </div>
                <div v-if="!hasAnyContent()" class="content-empty">
                  <el-empty description="暂无内容" :image-size="100" />
                </div>
              </div>
            </div>
          </section>

          <!-- 第二组页签：动态、评论、附件、关联项等 -->
          <section class="section-card tabs-card">
            <el-tabs v-model="secondaryTab" class="detail-tabs" :key="`secondary-tabs-${visible}-${localDefect?.id || ''}`">
              <el-tab-pane label="动态" name="activities">
                <div class="tab-content" v-if="secondaryTab === 'activities'">
                  <ActivityList
                    entity-type="defect"
                    :entity-id="localDefect.id"
                    :requirement="localDefect"
                    :status-options="statusOptions"
                    :priority-options="priorityOptions"
                    :users="users"
                    :key="`activities-${localDefect.id}`"
                  />
                </div>
              </el-tab-pane>

              <el-tab-pane label="评论" name="comments">
                <div class="tab-content" v-if="secondaryTab === 'comments'">
                  <CommentList
                    entity-type="defect"
                    :entity-id="localDefect.id"
                    :users="users"
                    @comment-count-change="handleCommentCountChange"
                    :key="`comments-${localDefect.id}`"
                  />
                </div>
              </el-tab-pane>

              <el-tab-pane label="附件" name="attachments">
                <div class="tab-content" v-if="secondaryTab === 'attachments'">
                  <AttachmentManager
                    :attachments="localDefect.attachments || []"
                    :upload-handler="handleUploadAttachment"
                    :delete-handler="handleDeleteAttachment"
                    :download-handler="handleDownloadAttachment"
                    :can-delete="true"
                    @upload-success="handleAttachmentMutation"
                    @delete-success="handleAttachmentMutation"
                    :key="`attachments-${localDefect.id}`"
                  />
                </div>
              </el-tab-pane>

              <el-tab-pane label="关联项" name="associations">
                <div class="tab-content" v-if="secondaryTab === 'associations'">
                  <DefectAssociations
                    :defect-id="localDefect.id"
                    :defect="localDefect"
                    :project-id="localDefect.project_id"
                    @updated="handleAssociationsUpdated"
                    :key="`associations-${localDefect.id}`"
                  />
                </div>
              </el-tab-pane>

              <el-tab-pane label="其他" name="others">
                <div class="tab-content">
                  <div class="other-info">
                    <div class="other-section">
                      <div class="other-title">时间信息</div>
                      <div class="other-row">
                        <span class="other-label">创建时间</span>
                        <span class="other-value">{{ formatDateTimeDisplay(localDefect.created_at) }}</span>
                      </div>
                      <div class="other-row">
                        <span class="other-label">更新时间</span>
                        <span class="other-value">{{ formatDateTimeDisplay(localDefect.updated_at) }}</span>
                      </div>
                      <div class="other-row" v-if="localDefect.found_date">
                        <span class="other-label">发现日期</span>
                        <span class="other-value">{{ formatDateTimeDisplay(localDefect.found_date) }}</span>
                      </div>
                      <div class="other-row" v-if="localDefect.resolved_date">
                        <span class="other-label">解决日期</span>
                        <span class="other-value">{{ formatDateTimeDisplay(localDefect.resolved_date) }}</span>
                      </div>
                      <div class="other-row" v-if="localDefect.verified_date">
                        <span class="other-label">验证日期</span>
                        <span class="other-value">{{ formatDateTimeDisplay(localDefect.verified_date) }}</span>
                      </div>
                    </div>

                    <div class="other-section">
                      <div class="other-title">标签</div>
                      <div class="tag-list">
                        <el-tag v-for="tag in localDefect.tags" :key="tag" size="small" closable @close="handleRemoveTag(tag)">
                          {{ tag }}
                        </el-tag>
                        <el-button size="small" type="text" @click="showAddTagInput = true" v-if="localDefect.tags.length < 10">
                          <el-icon-plus />
                          添加标签
                        </el-button>
                        <el-input
                          v-if="showAddTagInput"
                          v-model="newTag"
                          placeholder="输入标签"
                          size="small"
                          @keyup.enter="handleAddTag"
                          @blur="showAddTagInput = false"
                          ref="tagInputRef"
                        />
                      </div>
                    </div>
                  </div>
                </div>
              </el-tab-pane>
            </el-tabs>
          </section>
        </div>

        <aside class="side-column">
          <section class="info-card">
            <div class="info-card-title">基础字段</div>
            <div class="info-form-group" ref="statusFieldRef">
              <label class="info-label">状态 <span class="required">*</span></label>
              <el-select
                :model-value="localDefect.status"
                placeholder="请选择状态"
                size="default"
                :class="{ 'field-error': fieldErrors.status }"
                @update:model-value="(value: string) => handleSaveField('status', value)"
                @change="clearFieldError('status')"
              >
                <el-option
                  v-for="option in statusOptions"
                  :key="option.value"
                  :value="option.value"
                  :label="option.label"
                />
              </el-select>
              <div v-if="fieldErrors.status" class="error-message">{{ fieldErrors.status }}</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">优先级</label>
              <el-select
                :model-value="localDefect.priority"
                placeholder="请选择优先级"
                size="default"
                @update:model-value="(value: string) => handleSaveField('priority', value)"
              >
                <el-option
                  v-for="option in priorityOptions"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
            </div>
            <div class="info-form-group">
              <label class="info-label">严重程度</label>
              <el-select
                :model-value="localDefect.severity"
                placeholder="请选择严重程度"
                size="default"
                @update:model-value="(value: string) => handleSaveField('severity', value)"
              >
                <el-option
                  v-for="option in severityOptions"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
            </div>
            <div class="info-form-group">
              <label class="info-label">缺陷类型</label>
              <el-select
                :model-value="localDefect.type"
                placeholder="请选择类型"
                size="default"
                @update:model-value="(value: string) => handleSaveField('type', value)"
              >
                <el-option
                  v-for="option in typeOptions"
                  :key="option.value"
                  :value="option.value"
                  :label="option.label"
                />
              </el-select>
            </div>
            <div class="info-form-group">
              <label class="info-label">缺陷来源</label>
              <el-select
                :model-value="localDefect.source"
                placeholder="请选择来源"
                size="default"
                @update:model-value="(value: string) => handleSaveField('source', value)"
              >
                <el-option
                  v-for="option in sourceOptions"
                  :key="option.value"
                  :value="option.value"
                  :label="option.label"
                />
              </el-select>
            </div>
            <div class="info-form-group" ref="projectIdFieldRef">
              <label class="info-label">所属项目</label>
              <el-select
                :model-value="localDefect.project_id"
                placeholder="请选择项目"
                filterable
                size="default"
                :class="{ 'field-error': fieldErrors.project_id }"
                @update:model-value="(value: string) => handleSaveField('project_id', value)"
                @change="clearFieldError('project_id')"
              >
                <el-option
                  v-for="project in projects"
                  :key="project.id"
                  :label="project.name"
                  :value="project.id"
                />
              </el-select>
              <div v-if="fieldErrors.project_id" class="error-message">{{ fieldErrors.project_id }}</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">关联版本</label>
              <el-select
                :model-value="localDefect.version_id"
                placeholder="请选择版本"
                filterable
                size="default"
                :loading="loadingVersions"
                :disabled="!localDefect.project_id"
                @update:model-value="(value: string | null) => handleSaveField('version_id', value || null)"
              >
                <el-option
                  v-for="version in availableVersionOptions"
                  :key="version.id"
                  :label="version.name"
                  :value="version.id"
                />
              </el-select>
              <div v-if="!localDefect.project_id" class="field-hint" style="font-size: 12px; color: #909399; margin-top: 4px;">
                请先选择所属项目
              </div>
            </div>
            <div class="info-form-group">
              <label class="info-label">缺陷标签</label>
              <el-select
                :model-value="localDefect.tags || []"
                multiple
                filterable
                allow-create
                default-first-option
                collapse-tags
                collapse-tags-tooltip
                placeholder="请选择标签或输入新标签"
                size="default"
                @update:model-value="(value: string[]) => handleSaveField('tags', value)"
              >
                <el-option
                  v-for="tag in commonTagOptions"
                  :key="tag"
                  :label="tag"
                  :value="tag"
                />
              </el-select>
            </div>
          </section>

          <section class="info-card">
            <div class="info-card-title">人员</div>
            <div class="info-form-group" ref="reporterIdFieldRef">
              <label class="info-label">报告人 <span class="required">*</span></label>
              <el-select
                :model-value="localDefect.reporter_id"
                placeholder="请选择报告人"
                filterable
                clearable
                size="default"
                :loading="loadingData"
                :class="{ 'field-error': fieldErrors.reporter_id }"
                @update:model-value="(value: string | null) => handleSaveField('reporter_id', value ?? '')"
                @change="clearFieldError('reporter_id')"
              >
                <template #prefix>
                  <UserAvatar
                    v-if="localDefect.reporter_id && !loadingData"
                    :user="getUserById(localDefect.reporter_id)"
                    size="small"
                    circle
                    class="select-prefix-avatar"
                  />
                </template>
                <el-option
                  v-for="user in users"
                  :key="user.id"
                  :label="user.name"
                  :value="user.id"
                >
                  <div class="user-option">
                    <UserAvatar
                      :user="getUserObject(user)"
                      size="small"
                      circle
                    />
                    <span>{{ user.name }}</span>
                  </div>
                </el-option>
              </el-select>
              <div v-if="fieldErrors.reporter_id" class="error-message">{{ fieldErrors.reporter_id }}</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">负责人</label>
              <el-select
                :model-value="localDefect.assignee_id"
                placeholder="请选择负责人（可选）"
                filterable
                clearable
                size="default"
                :loading="loadingData"
                @update:model-value="(value: string | null) => handleSaveField('assignee_id', value ?? '')"
              >
                <template #prefix>
                  <UserAvatar
                    v-if="localDefect.assignee_id && !loadingData"
                    :user="getUserById(localDefect.assignee_id)"
                    size="small"
                    circle
                    class="select-prefix-avatar"
                  />
                </template>
                <el-option
                  v-for="user in users"
                  :key="user.id"
                  :label="user.name"
                  :value="user.id"
                >
                  <div class="user-option">
                    <UserAvatar
                      :user="getUserObject(user)"
                      size="small"
                      circle
                    />
                    <span>{{ user.name }}</span>
                  </div>
                </el-option>
              </el-select>
            </div>
            <div class="info-form-group">
              <label class="info-label">验证人</label>
              <el-select
                :model-value="localDefect.verifier_id"
                placeholder="请选择验证人（可选）"
                filterable
                clearable
                size="default"
                :loading="loadingData"
                @update:model-value="(value: string | null) => handleSaveField('verifier_id', value ?? '')"
              >
                <template #prefix>
                  <UserAvatar
                    v-if="localDefect.verifier_id && !loadingData"
                    :user="getUserById(localDefect.verifier_id)"
                    size="small"
                    circle
                    class="select-prefix-avatar"
                  />
                </template>
                <el-option
                  v-for="user in users"
                  :key="user.id"
                  :label="user.name"
                  :value="user.id"
                >
                  <div class="user-option">
                    <UserAvatar
                      :user="getUserObject(user)"
                      size="small"
                      circle
                    />
                    <span>{{ user.name }}</span>
                  </div>
                </el-option>
              </el-select>
            </div>
          </section>

          <section class="info-card">
            <div class="info-card-title">时间信息</div>
            <div class="info-form-group">
              <label class="info-label">发现时间</label>
              <el-date-picker
                :model-value="formatDateTimeForPicker(localDefect.found_date)"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择发现时间"
                size="default"
                style="width: 100%"
                @update:model-value="(value: string | null) => handleSaveField('found_date', value || null)"
              />
            </div>
            <div class="info-form-group">
              <label class="info-label">解决时间</label>
              <el-date-picker
                :model-value="formatDateTimeForPicker(localDefect.resolved_date)"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择解决时间"
                size="default"
                style="width: 100%"
                @update:model-value="(value: string | null) => handleSaveField('resolved_date', value || null)"
              />
              <div class="field-hint">可手动设置，状态变更为"已解决"时也会自动更新</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">验证时间</label>
              <el-date-picker
                :model-value="formatDateTimeForPicker(localDefect.verified_date)"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择验证时间"
                size="default"
                style="width: 100%"
                @update:model-value="(value: string | null) => handleSaveField('verified_date', value || null)"
              />
              <div class="field-hint">可手动设置，状态变更为"已验证"时也会自动更新</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">完成时间</label>
              <el-date-picker
                :model-value="formatDateTimeForPicker(localDefect.completed_at)"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择完成时间"
                size="default"
                style="width: 100%"
                @update:model-value="(value: string | null) => handleSaveField('completed_at', value || null)"
              />
              <div class="field-hint">设置完成时间后，系统将根据此时间统计逾期数据</div>
            </div>
            <div class="info-form-group">
              <label class="info-label">实际完成时间</label>
              <el-date-picker
                :model-value="formatDateTimeForPicker(localDefect.actual_completed_at)"
                type="datetime"
                value-format="YYYY-MM-DD HH:mm:ss"
                format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择实际完成时间"
                size="default"
                style="width: 100%"
                @update:model-value="(value: string | null) => handleSaveField('actual_completed_at', value || null)"
              />
              <div class="field-hint">可手动设置，状态变更为"已关闭"时也会自动更新</div>
            </div>
          </section>

          <section class="info-card">
            <div class="info-card-title">环境信息</div>
            <div class="info-form-group">
              <label class="info-label">环境类型</label>
              <el-select
                :model-value="environmentType"
                placeholder="请选择环境"
                size="default"
                @update:model-value="(value: string) => handleSaveEnvironment(value)"
              >
                <el-option
                  v-for="option in environmentOptions"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
            </div>
          </section>
        </aside>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed, nextTick } from 'vue'
import { ElMessage, ElInput } from 'element-plus'
import type { Defect, DefectEnvironmentInfo } from '@/api/defect'
import type { User } from '@/types/user'
import { defectAPI } from '@/api/defect'
import { ResponseParser } from '@/utils/responseParser'
import CommentList from '@/components/common/CommentList.vue'
import ActivityList from '@/components/common/ActivityList.vue'
import EnhancedRichTextEditor from '@/components/common/EnhancedRichTextEditor.vue'
import AttachmentManager from '@/components/common/AttachmentManager.vue'
import UserAvatar from '@/components/ui/UserAvatar.vue'
import DefectAssociations from '@/components/defect/DefectAssociations.vue'
import { useDefectStates } from '@/composables/useDefectStates'
import { useDefectOptions } from '@/composables/useDefectOptions'
import { getUsers } from '@/api/users'
import { getProjectList } from '@/api/project'
import { DEFECT_TYPE_OPTIONS, getDefectTypeLabel } from '@/types/defect'
import { versionAPI } from '@/api/version'

interface StatusOption {
  value: string
  label: string
}

interface PriorityOption {
  value: string
  label: string
}

interface SeverityOption {
  value: string
  label: string
}

interface TypeOption {
  value: string
  label: string
}

interface SourceOption {
  value: string
  label: string
}

interface UserOption {
  id: string
  name: string
  real_name?: string
  avatar?: string
}

interface ProjectOption {
  id: string
  name: string
}

interface VersionOption {
  id: string
  name: string
  project_id?: string
}

// Props
const props = defineProps<{
  visible: boolean
  defect?: Defect | null
  statusOptions?: StatusOption[]
  priorityOptions?: PriorityOption[]
  severityOptions?: SeverityOption[]
  typeOptions?: TypeOption[]
  sourceOptions?: SourceOption[]
  users?: UserOption[]
  projects?: ProjectOption[]
  versionOptions?: VersionOption[]
  commonTags?: string[]
}>()

// Emits
const emit = defineEmits<{
  'update:visible': [value: boolean]
  'updated': [defectId: string]
}>()

// Composables
const { statusOptions: defectStatusOptions, loadStates: loadDefectStates } = useDefectStates()
const { formattedPriorityOptions, formattedSeverityOptions, formattedSourceOptions: defectSourceOptions, getSourceName, loadOptions: loadDefectOptions } = useDefectOptions()

// Data
const localDefect = ref<Defect | null>(null)
const originalDefect = ref<Defect | null>(null)
const fieldErrors = reactive<Record<string, string>>({})
const isUpdatingFromProps = ref(false) // 防止循环更新的标志位
const savingFields = reactive<Record<string, boolean>>({})

// Options data
const statusOptions = computed(() => {
  if (props.statusOptions && props.statusOptions.length > 0) {
    return props.statusOptions
  }
  return defectStatusOptions.value.map((state: any) => ({
    value: state.code || state.value,
    label: state.name || state.label
  }))
})

const priorityOptions = computed(() => {
  if (props.priorityOptions && props.priorityOptions.length > 0) {
    return props.priorityOptions
  }
  return formattedPriorityOptions.value.map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

const severityOptions = computed(() => {
  if (props.severityOptions && props.severityOptions.length > 0) {
    return props.severityOptions
  }
  return formattedSeverityOptions.value.map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

const typeOptions = computed(() => {
  if (props.typeOptions && props.typeOptions.length > 0) {
    return props.typeOptions
  }
  return DEFECT_TYPE_OPTIONS.map(type => ({
    value: type.value,
    label: type.label
  }))
})

const sourceOptions = computed(() => {
  if (props.sourceOptions && props.sourceOptions.length > 0) {
    return props.sourceOptions
  }
  return defectSourceOptions.value.map((opt: any) => ({
    value: opt.value || opt.code,
    label: opt.label || opt.name
  }))
})

const users = ref<UserOption[]>(props.users || [])
const projects = ref<ProjectOption[]>(props.projects || [])
const versionOptions = ref<VersionOption[]>(props.versionOptions || [])

// 计算属性 - 可用的版本选项
const availableVersionOptions = computed(() => {
  if (!localDefect.value?.project_id) {
    return versionOptions.value
  }
  return versionOptions.value.filter((version: VersionOption) => 
    !version.project_id || version.project_id === localDefect.value?.project_id
  )
})

// Load data - 必须在 watch 之前定义，因为 watch 的 immediate 会在初始化时执行
const loadingData = ref(false)
const hasLoadedBaseData = ref(false) // 标记是否已加载基础数据（用户、项目等）
const loadData = async (forceReload = false) => {
  // 防止重复调用
  if (loadingData.value) {
    return
  }
  
  // 如果已经加载过基础数据且不是强制重新加载，跳过基础数据加载
  if (hasLoadedBaseData.value && !forceReload) {
    // 只加载版本数据（如果需要）
    if (localDefect.value?.project_id) {
      await loadVersionsByProject(localDefect.value.project_id)
    }
    return
  }
  
  try {
    loadingData.value = true
    
    // Load defect states
    await loadDefectStates()
    await loadDefectOptions()

    // Load users if not provided or users.value is empty
    if ((!props.users || props.users.length === 0) && users.value.length === 0) {
      try {
        const usersResponse = await getUsers({ page: 1, size: 200 })
        const parsedResult = ResponseParser.parseUserListResponse(usersResponse)
        if (parsedResult.items && parsedResult.items.length > 0) {
          users.value = parsedResult.items.map((user: any) => ({
            id: user.id,
            name: user.name || user.username || `用户${user.id}`,
            real_name: user.real_name || user.name || user.username || `用户${user.id}`,
            avatar: user.avatar || user.avatar_url || ''
          }))
        }
      } catch (error) {
        console.error('加载用户列表失败:', error)
        ElMessage.error('加载用户列表失败，请稍后重试')
      }
    } else if (props.users && props.users.length > 0) {
      // 如果 props.users 有值，同步到 users.value
      users.value = props.users
    }

    // Load projects if not provided
    if (!props.projects || props.projects.length === 0) {
      const projectsResponse = await getProjectList({ page: 1, size: 200 })
      const projectsData = (projectsResponse as any)?.data?.items || (projectsResponse as any)?.items || []
      if (projectsData.length > 0) {
        projects.value = projectsData.map((project: any) => ({
          id: project.id,
          name: project.name
        }))
      }
    }

    // Load versions if defect has project_id
    if (localDefect.value?.project_id) {
      await loadVersionsByProject(localDefect.value.project_id)
    }
    
    // 标记基础数据已加载
    hasLoadedBaseData.value = true
  } catch (error) {
    console.error('加载数据失败:', error)
  } finally {
    loadingData.value = false
  }
}

// 根据项目ID加载版本列表
const loadingVersions = ref(false)
const loadVersionsByProject = async (projectId: string) => {
  if (!projectId || loadingVersions.value) {
    return
  }

  try {
    loadingVersions.value = true
    const response = await versionAPI.getVersions({ 
      project_id: projectId, 
      limit: 200,
      sort_by: 'created_at',
      sort_order: 'desc'
    })
    
    if (response.success && response.data) {
      const versionsData = response.data.items || []
      versionOptions.value = versionsData.map((v: any) => ({
        id: v.id,
        name: v.name || v.version_number || `版本 ${v.id}`,
        project_id: v.project_id || projectId
      }))
    } else {
      versionOptions.value = []
    }
  } catch (error) {
    console.error('加载版本列表失败:', error)
    versionOptions.value = []
  } finally {
    loadingVersions.value = false
  }
}

// 监听 props.users 的变化，确保数据同步
watch(
  () => props.users,
  (newUsers) => {
    if (newUsers && newUsers.length > 0) {
      users.value = newUsers
      // 如果外部提供了用户数据，标记基础数据已加载
      hasLoadedBaseData.value = true
    } else if (props.visible && users.value.length === 0 && !hasLoadedBaseData.value && !loadingData.value) {
      // 如果 props.users 为空，但对话框已打开且用户列表为空，且未加载过基础数据，则加载用户数据
      loadData()
    }
  },
  { immediate: true, deep: true }
)

// 监听 props.projects 的变化，确保数据同步
watch(
  () => props.projects,
  (newProjects) => {
    if (newProjects && newProjects.length > 0) {
      projects.value = newProjects
    }
  },
  { immediate: true, deep: true }
)
const commonTagOptions = computed(() => {
  const tags = new Set<string>(props.commonTags || [])
  if (localDefect.value?.tags) {
    localDefect.value.tags.forEach(tag => tags.add(tag))
  }
  return Array.from(tags)
})

// Editing states
const editingContent = ref(false)
const savingContent = ref(false)
const combinedContent = ref('')

// Tabs
const secondaryTab = ref('activities')

// Environment options
const environmentOptions = [
  { value: 'development', label: '开发环境' },
  { value: 'testing', label: '测试环境' },
  { value: 'staging', label: '预发布环境' },
  { value: 'production', label: '生产环境' }
]

// Environment type computed
const environmentType = computed(() => {
  if (!localDefect.value?.environment_info) return ''
  // 从 environment_info.additional_info.environment 中获取环境类型
  // 后端 DefectEnvironmentInfo 结构：os, browser, version, device, resolution, additional_info
  const envInfo = localDefect.value.environment_info
  return envInfo?.additional_info?.environment || ''
})

const showAddTagInput = ref(false)
const newTag = ref('')
const tagInputRef = ref<InstanceType<typeof ElInput> | null>(null)

// Helper functions (defined before watchers to avoid initialization errors)
const formatDateTimeDisplay = (dateStr?: string) => {
  if (!dateStr) return '未设置'
  const date = new Date(dateStr)
  return date.toLocaleString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit'
  })
}

// 格式化日期时间为日期选择器需要的格式 (YYYY-MM-DD HH:mm:ss)
const formatDateTimeForPicker = (dateStr?: string | null): string | null => {
  if (!dateStr) return null
  
  try {
    // 如果已经是 YYYY-MM-DD HH:mm:ss 格式，直接返回
    if (dateStr.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/)) {
      return dateStr
    }
    
    // 处理 ISO 格式 (2024-01-01T12:00:00 或 2024-01-01T12:00:00Z)
    let date: Date
    if (dateStr.includes('T')) {
      date = new Date(dateStr)
    } else if (dateStr.match(/^\d{4}-\d{2}-\d{2}$/)) {
      // 如果只有日期，添加时间部分
      date = new Date(dateStr + 'T00:00:00')
    } else {
      // 尝试直接解析（可能已经是标准格式）
      date = new Date(dateStr)
    }
    
    if (isNaN(date.getTime())) {
      console.warn('无法解析日期时间:', dateStr)
      return null
    }
    
    // 格式化为 YYYY-MM-DD HH:mm:ss
    const year = date.getFullYear()
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    const hours = String(date.getHours()).padStart(2, '0')
    const minutes = String(date.getMinutes()).padStart(2, '0')
    const seconds = String(date.getSeconds()).padStart(2, '0')
    
    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
  } catch (error) {
    console.error('格式化日期时间失败:', error, dateStr)
    return null
  }
}

// 根据用户ID获取用户对象（用于头像显示）
const getUserById = (userId?: string | null): User | null => {
  if (!userId) return null
  const userOption = users.value.find(u => u.id === userId)
  if (!userOption) return null
  return getUserObject(userOption)
}

// 将 UserOption 转换为 User 对象格式
const getUserObject = (userOption: UserOption): User => {
  return {
    id: userOption.id,
    name: userOption.name,
    username: userOption.name,
    email: '',
    avatar: userOption.avatar,
    roles: [],
    status: 'active',
    is_verified: false,
    created_at: '',
    updated_at: ''
  } as User
}

// 检查内容是否有实际文本（去除 HTML 标签后）
const hasContent = (content?: string | null): boolean => {
  if (!content) return false
  // 去除 HTML 标签
  const text = content.replace(/<[^>]*>/g, '').trim()
  // 检查是否还有实际文本内容
  return text.length > 0
}

// 检查是否有任何内容
const hasAnyContent = (): boolean => {
  if (!localDefect.value) return false
  return (
    hasContent(localDefect.value.description) ||
    hasContent(localDefect.value.steps_to_reproduce) ||
    hasContent(localDefect.value.expected_result) ||
    hasContent(localDefect.value.actual_result)
  )
}

// 合并内容函数：将四个字段合并为一个富文本内容
const combineContent = (defect: Defect | null) => {
  if (!defect) return ''
  
  const parts = []
  
  if (defect.description) {
    parts.push(`<h3>缺陷描述</h3>${defect.description}`)
  }
  
  if (defect.steps_to_reproduce) {
    parts.push(`<h3>复现步骤</h3>${defect.steps_to_reproduce}`)
  }
  
  if (defect.expected_result) {
    parts.push(`<h3>期望结果</h3>${defect.expected_result}`)
  }
  
  if (defect.actual_result) {
    parts.push(`<h3>实际结果</h3>${defect.actual_result}`)
  }
  
  return parts.join('<br><br>')
}

// 解析合并内容：从富文本内容中提取四个字段
const parseContent = (content: string) => {
  if (!content) {
    return {
      description: '',
      steps_to_reproduce: '',
      expected_result: '',
      actual_result: ''
    }
  }
  
  // 使用正则表达式分割内容
  const sections: Record<string, string> = {}
  const regex = /<h3>(.*?)<\/h3>(.*?)(?=<h3>|$)/gs
  let match
  
  while ((match = regex.exec(content)) !== null) {
    const title = match[1].trim()
    const text = match[2].trim()
    
    if (title === '缺陷描述') {
      sections.description = text
    } else if (title === '复现步骤') {
      sections.steps_to_reproduce = text
    } else if (title === '期望结果') {
      sections.expected_result = text
    } else if (title === '实际结果') {
      sections.actual_result = text
    }
  }
  
  // 如果没有找到标题，尝试按顺序分配（兼容旧数据）
  if (Object.keys(sections).length === 0) {
    const parts = content.split('<br><br>')
    sections.description = parts[0] || ''
    sections.steps_to_reproduce = parts[1] || ''
    sections.expected_result = parts[2] || ''
    sections.actual_result = parts[3] || ''
  }
  
  return {
    description: sections.description || '',
    steps_to_reproduce: sections.steps_to_reproduce || '',
    expected_result: sections.expected_result || '',
    actual_result: sections.actual_result || ''
  }
}

// Attachment handlers
const handleUploadAttachment = async (_file: File) => {
  if (!localDefect.value?.id) {
    throw new Error('缺陷ID不存在')
  }
  // TODO: Implement attachment upload
  return Promise.resolve()
}

const handleDeleteAttachment = async (attachment: any) => {
  if (!localDefect.value?.id) {
    throw new Error('缺陷ID不存在')
  }
  const attachmentId = typeof attachment === 'string' ? attachment : attachment.id
  // TODO: Implement attachment delete
  console.log('Delete attachment:', attachmentId)
  return Promise.resolve()
}

const handleDownloadAttachment = async (attachment: any) => {
  if (!localDefect.value?.id) {
    throw new Error('缺陷ID不存在')
  }
  const attachmentId = typeof attachment === 'string' ? attachment : attachment.id
  // TODO: Implement attachment download
  console.log('Download attachment:', attachmentId)
  return Promise.resolve()
}

const handleAttachmentMutation = () => {
  if (localDefect.value?.id) {
    emit('updated', localDefect.value.id)
  }
}

const handleCommentCountChange = () => {
  // Handle comment count change if needed
}

const handleAssociationsUpdated = async () => {
  // 重新加载缺陷数据以获取最新的关联信息
  if (localDefect.value?.id) {
    try {
      const response = await defectAPI.getDefectById(localDefect.value.id)
      if (response && response.success && response.data) {
        // 使用标志位防止触发 watch
        isUpdatingFromProps.value = true
        try {
          localDefect.value = response.data
          originalDefect.value = { ...response.data }
          // 更新合并内容
          combinedContent.value = combineContent(response.data)
        } finally {
          isUpdatingFromProps.value = false
        }
        // 延迟 emit，避免立即触发父组件更新导致循环
        await nextTick()
        emit('updated', localDefect.value.id)
      }
    } catch (error) {
      console.error('重新加载缺陷数据失败:', error)
    }
  }
}

// Watchers
watch(
  () => props.visible,
  (visible, oldVisible) => {
    if (visible) {
      // 只在对话框打开时加载数据，且避免重复加载
      if (!oldVisible && !loadingData.value) {
        loadData()
      }
    } else {
      // 当对话框关闭时，重置标签页状态，避免 DOM 更新问题
      secondaryTab.value = 'activities'
      editingContent.value = false
    }
  }
)

watch(
  () => props.defect,
  async (newDefect, oldDefect) => {
    // 防止循环更新：如果正在从 props 更新，跳过
    if (isUpdatingFromProps.value) {
      return
    }
    
    // 如果新旧缺陷ID相同，且数据没有实质性变化，跳过更新
    if (newDefect && oldDefect && newDefect.id === oldDefect.id) {
      // 比较关键字段，如果相同则跳过
      const keyFields = ['status', 'priority', 'severity', 'assignee_id', 'resolved_date', 'verified_date', 'completed_at', 'actual_completed_at', 'updated_at']
      const hasSignificantChange = keyFields.some(field => {
        const newVal = (newDefect as any)[field]
        const oldVal = (oldDefect as any)[field]
        return newVal !== oldVal
      })
      
      // 如果没有实质性变化，跳过更新
      if (!hasSignificantChange && localDefect.value?.id === newDefect.id) {
        return
      }
    }
    
    if (newDefect) {
      // 确保用户数据已加载（只在必要时加载，避免重复）
      if (!hasLoadedBaseData.value && !loadingData.value) {
        await loadData()
      }
      // 使用 nextTick 确保 DOM 更新完成
      await nextTick()
      isUpdatingFromProps.value = true
      try {
        // 处理版本数据：从 versions 数组中提取第一个版本的ID作为 version_id（向后兼容）
        const defectData: any = { ...newDefect }
        if (defectData.versions && Array.isArray(defectData.versions) && defectData.versions.length > 0) {
          // 如果后端返回了 versions 数组，提取第一个版本的ID
          defectData.version_id = defectData.versions[0].id || defectData.versions[0]._id || undefined
        } else if (!defectData.version_id) {
          // 如果没有 versions 数组也没有 version_id，设置为 undefined
          defectData.version_id = undefined
        }
        
        localDefect.value = defectData
        originalDefect.value = { ...newDefect }
        // 初始化合并内容
        combinedContent.value = combineContent(newDefect)
        // 如果缺陷有项目ID，加载对应的版本列表（避免在 watch project_id 中重复加载）
        if (newDefect.project_id && (!oldDefect || oldDefect.project_id !== newDefect.project_id)) {
          await loadVersionsByProject(newDefect.project_id)
        }
      } finally {
        isUpdatingFromProps.value = false
      }
    } else {
      // 当 defect 为 null 时，清空本地数据
      isUpdatingFromProps.value = true
      try {
        localDefect.value = null
        originalDefect.value = null
        combinedContent.value = ''
        versionOptions.value = []
      } finally {
        isUpdatingFromProps.value = false
      }
    }
  },
  { deep: true, immediate: true }
)

// 监听项目ID变化，自动加载版本列表
// 注意：如果是在 watch defect 中已经加载过，这里会跳过（通过检查是否正在更新来避免重复）
watch(
  () => localDefect.value?.project_id,
  async (newProjectId, oldProjectId) => {
    // 如果正在从 props 更新，跳过（避免重复加载）
    if (isUpdatingFromProps.value) {
      return
    }
    
    if (newProjectId && newProjectId !== oldProjectId) {
      await loadVersionsByProject(newProjectId)
    } else if (!newProjectId) {
      // 如果项目ID被清空，清空版本列表
      versionOptions.value = []
    }
  }
)

// Load data on mount - 移除，因为 watch visible 已经处理了
// onMounted 中的加载逻辑已由 watch(() => props.visible) 处理，避免重复调用

// Methods
const handleClose = () => {
  // 取消所有编辑状态
  cancelAllEdits()
  // 清除错误信息
  Object.keys(fieldErrors).forEach(key => delete fieldErrors[key])
  // 关闭对话框
  emit('update:visible', false)
}

const cancelAllEdits = () => {
  editingContent.value = false
  // 恢复合并内容
  if (localDefect.value) {
    combinedContent.value = combineContent(localDefect.value)
  }
  showAddTagInput.value = false
  newTag.value = ''
}

const clearFieldError = (field: string) => {
  delete fieldErrors[field]
}

// Status handling
// 使用 composables 提供的函数，不再硬编码
const { getStatusType: getDefectStatusTypeFromComposable, getStatusName: getDefectStatusNameFromComposable } = useDefectStates()
const { getPriorityType: getDefectPriorityTypeFromComposable, getPriorityName: getDefectPriorityNameFromComposable } = useDefectOptions()

const getStatusType = (status: string) => {
  if (!status) return 'info'
  return getDefectStatusTypeFromComposable(status)
}

const getStatusText = (status: string) => {
  if (!status) return '未设置状态'
  return getDefectStatusNameFromComposable(status)
}

// Priority handling
const getPriorityType = (priority: string) => {
  if (!priority) return 'info'
  return getDefectPriorityTypeFromComposable(priority)
}

const getPriorityText = (priority: string) => {
  if (!priority) return '未设置优先级'
  return getDefectPriorityNameFromComposable(priority)
}

// Severity handling - 使用 composables 提供的函数
const { getSeverityType: getDefectSeverityTypeFromComposable, getSeverityName: getDefectSeverityNameFromComposable } = useDefectOptions()

const getSeverityType = (severity: string) => {
  if (!severity) return 'info'
  return getDefectSeverityTypeFromComposable(severity)
}

const getSeverityText = (severity: string) => {
  if (!severity) return '未设置严重程度'
  return getDefectSeverityNameFromComposable(severity)
}

// Type handling - 使用统一的类型定义
const getTypeText = (type: string) => {
  if (!type) return ''
  const label = getDefectTypeLabel(type)
  if (label) return label
  // 回退到 props 中的选项
  const option = props.typeOptions?.find(option => option.value === type)
  return option?.label || type
}

// Source handling - 使用统一的类型定义
const getSourceText = (source: string) => {
  if (!source) return ''
  // 首先尝试从 composable 获取
  const name = getSourceName(source)
  if (name && name !== source) return name
  // 回退到 props 中的选项
  const option = props.sourceOptions?.find(option => option.value === source)
  return option?.label || source
}

// Save handling
const handleSaveField = async (field: keyof Defect, value?: any) => {
  // If value is provided, update localDefect first
  if (value !== undefined && localDefect.value) {
    ;(localDefect.value as any)[field] = value
  }
  if (!localDefect.value || !localDefect.value.id) return
  if (!originalDefect.value) return

  const previous = originalDefect.value[field]
  const nextValue = localDefect.value[field]

  // 比较值是否变化（处理 null/undefined/空字符串的等价性）
  const isEqual = (a: any, b: any) => {
    if (a === b) return true
    if ((a === null || a === undefined || a === '') && (b === null || b === undefined || b === '')) return true
    if (Array.isArray(a) && Array.isArray(b)) {
      if (a.length !== b.length) return false
      return a.every((val, idx) => val === b[idx])
    }
    return false
  }

  if (isEqual(nextValue, previous)) {
    return
  }

    // 更新本地状态
    ;(originalDefect.value as any)[field] = nextValue

    // 防止重复提交
    if (savingFields[field as string]) {
      return
    }

    savingFields[field as string] = true
  try {
    // 构建请求载荷
    let payloadValue: any = nextValue
    const updatePayload: any = { [field]: payloadValue }

    // 特殊处理：状态变更时自动更新时间字段
    if (field === 'status' && payloadValue && typeof payloadValue === 'string') {
      const currentTime = new Date().toISOString().replace('Z', '').slice(0, 19) // YYYY-MM-DDTHH:mm:ss
      const statusLabel = statusOptions.value.find(opt => opt.value === payloadValue)?.label || ''
      
      // 根据状态标签判断需要更新的时间字段
      // 如果状态包含"解决"关键词，自动设置解决时间（如果还未设置）
      if (statusLabel.includes('解决') && 
          !localDefect.value?.resolved_date) {
        updatePayload.resolved_date = currentTime
        // 同时更新本地状态
        if (localDefect.value) {
          ;(localDefect.value as any).resolved_date = currentTime
        }
      }
      
      // 如果状态包含"验证"关键词，自动设置验证时间（如果还未设置）
      if (statusLabel.includes('验证') && 
          !localDefect.value?.verified_date) {
        updatePayload.verified_date = currentTime
        // 同时更新本地状态
        if (localDefect.value) {
          ;(localDefect.value as any).verified_date = currentTime
        }
      }
      
      // 如果状态包含"关闭"关键词，自动设置实际完成时间（如果还未设置）
      // 注意：完成时间（completed_at）由用户手动设置，用于统计逾期，不应自动覆盖
      if (statusLabel.includes('关闭') && 
          !localDefect.value?.actual_completed_at) {
        updatePayload.actual_completed_at = currentTime
        // 同时更新本地状态
        if (localDefect.value) {
          ;(localDefect.value as any).actual_completed_at = currentTime
        }
        // 如果用户没有手动设置完成时间，则使用当前时间作为完成时间
        if (!localDefect.value?.completed_at) {
          updatePayload.completed_at = currentTime
          if (localDefect.value) {
            ;(localDefect.value as any).completed_at = currentTime
          }
        }
      }
    }

    // 特殊处理：空字符串转为 null
    if (payloadValue === '') {
      if (field === 'assignee_id' || field === 'reporter_id' || field === 'verifier_id' || field === 'version_id' || field === 'found_date' || field === 'resolved_date' || field === 'verified_date' || field === 'completed_at' || field === 'actual_completed_at') {
        payloadValue = null as any
        updatePayload[field] = null
      }
    }

    // 特殊处理：所有时间字段都需要转换为 ISO datetime 格式 (YYYY-MM-DDTHH:mm:ss)
    Object.keys(updatePayload).forEach(key => {
      if (key === 'found_date' || key === 'resolved_date' || key === 'verified_date' || 
          key === 'completed_at' || key === 'actual_completed_at') {
        const value = updatePayload[key]
        if (value === null || value === undefined) {
          updatePayload[key] = null
        } else if (typeof value === 'string') {
          // 将 "YYYY-MM-DD HH:mm:ss" 格式转换为 "YYYY-MM-DDTHH:mm:ss" 格式（ISO 格式）
          if (value.includes(' ')) {
            updatePayload[key] = value.replace(' ', 'T')
          } else if (!value.includes('T') && value.match(/^\d{4}-\d{2}-\d{2}$/)) {
            // 如果只有日期，添加时间部分（默认00:00:00）
            updatePayload[key] = `${value}T00:00:00`
          }
        }
      }
    })

    const response = await defectAPI.updateDefect(localDefect.value.id, updatePayload)
    const parsed = ResponseParser.parseResponse(response)
    if (!parsed.success) {
      throw new Error(parsed.message || '更新失败')
    }

    // 对于时间字段，需要重新获取数据以确保格式正确和回填成功
    const timeFields = ['found_date', 'resolved_date', 'verified_date', 'completed_at', 'actual_completed_at']
    const shouldRefresh = Object.keys(updatePayload).length > 1 || timeFields.includes(field)

    // 如果更新了多个字段或时间字段，需要重新获取缺陷数据以同步所有字段
    if (shouldRefresh && localDefect.value) {
      try {
        const defectResponse = await defectAPI.getDefectById(localDefect.value.id)
        const defectParsed = ResponseParser.parseResponse(defectResponse)
        if (defectParsed.success && defectParsed.data) {
          const updatedDefect = defectParsed.data as Defect
          // 使用标志位防止触发 watch
          isUpdatingFromProps.value = true
          try {
            if (Object.keys(updatePayload).length > 1) {
              // 如果更新了多个字段，完全替换数据
              localDefect.value = { ...updatedDefect }
              originalDefect.value = { ...updatedDefect }
              // 更新合并内容
              combinedContent.value = combineContent(updatedDefect)
            } else if (timeFields.includes(field)) {
              // 如果只更新了单个时间字段，只更新该字段
              if (updatedDefect[field as keyof Defect] !== undefined) {
                ;(localDefect.value as any)[field] = updatedDefect[field as keyof Defect]
                ;(originalDefect.value as any)[field] = updatedDefect[field as keyof Defect]
              }
            }
          } finally {
            isUpdatingFromProps.value = false
          }
        }
      } catch (refreshError) {
        console.error('刷新缺陷数据失败:', refreshError)
        // 即使刷新失败，也继续执行，因为主要更新已经成功
        // 对于时间字段，如果刷新失败，使用转换后的 ISO 格式更新本地状态作为后备方案
        if (timeFields.includes(field) && localDefect.value) {
          const convertedValue = updatePayload[field]
          if (convertedValue !== undefined) {
            ;(localDefect.value as any)[field] = convertedValue
            ;(originalDefect.value as any)[field] = convertedValue
          }
        }
      }
    }

    // 延迟 emit，避免立即触发父组件更新导致循环
    if (localDefect.value) {
      await nextTick()
      emit('updated', localDefect.value.id)
    }
    ElMessage.success('已更新')
  } catch (error) {
    // 恢复原值
    if (localDefect.value && originalDefect.value) {
      ;(localDefect.value as any)[field] = (originalDefect.value as any)[field]
      ;(originalDefect.value as any)[field] = previous
    }
    const message = ResponseParser.extractMessage(error) || '更新失败'
    ElMessage.error(message)
    fieldErrors[field] = message
  } finally {
    savingFields[field as string] = false
  }
}

// Content editing - 合并的富文本编辑
const cancelEditContent = () => {
  if (localDefect.value) {
    combinedContent.value = combineContent(localDefect.value)
  }
  editingContent.value = false
}

const saveContent = async () => {
  if (!localDefect.value || !localDefect.value.id) return
  
  savingContent.value = true
  try {
    // 解析合并内容为四个字段
    const parsed = parseContent(combinedContent.value)
    
    // 更新本地数据
    if (localDefect.value) {
      localDefect.value.description = parsed.description
      localDefect.value.steps_to_reproduce = parsed.steps_to_reproduce
      localDefect.value.expected_result = parsed.expected_result
      localDefect.value.actual_result = parsed.actual_result
    }
    
    // 保存到后端
    const response = await defectAPI.updateDefect(localDefect.value.id, {
      description: parsed.description,
      steps_to_reproduce: parsed.steps_to_reproduce,
      expected_result: parsed.expected_result,
      actual_result: parsed.actual_result
    })
    
    const result = ResponseParser.parseResponse(response)
    if (!result.success) {
      throw new Error(result.message || '更新失败')
    }

    // 更新原始数据
    if (originalDefect.value) {
      originalDefect.value.description = parsed.description
      originalDefect.value.steps_to_reproduce = parsed.steps_to_reproduce
      originalDefect.value.expected_result = parsed.expected_result
      originalDefect.value.actual_result = parsed.actual_result
    }

    editingContent.value = false
    emit('updated', localDefect.value.id)
    ElMessage.success('已更新缺陷详情')
  } catch (error) {
    const message = ResponseParser.extractMessage(error) || '更新失败'
    ElMessage.error(message)
    // 恢复合并内容
    if (localDefect.value) {
      combinedContent.value = combineContent(localDefect.value)
    }
  } finally {
    savingContent.value = false
  }
}

// Environment saving - 环境信息下拉选择
const handleSaveEnvironment = async (value: string) => {
  if (!localDefect.value || !localDefect.value.id) return
  
  try {
    // 构建环境信息对象
    const environmentInfo: DefectEnvironmentInfo = {
      ...localDefect.value.environment_info,
      additional_info: {
        ...(localDefect.value.environment_info?.additional_info || {}),
        environment: value
      }
    }
    
    const response = await defectAPI.updateDefect(localDefect.value.id, { 
      environment_info: environmentInfo 
    })
    
    const parsed = ResponseParser.parseResponse(response)
    if (!parsed.success) {
      throw new Error(parsed.message || '更新失败')
    }

    // 更新本地数据
    if (localDefect.value && originalDefect.value) {
      localDefect.value.environment_info = environmentInfo
      originalDefect.value.environment_info = environmentInfo
    }

    emit('updated', localDefect.value.id)
    ElMessage.success('已更新环境信息')
  } catch (error) {
    const message = ResponseParser.extractMessage(error) || '更新失败'
    ElMessage.error(message)
  }
}

// Tag handling
const handleAddTag = () => {
  if (!localDefect.value || !newTag.value.trim() || localDefect.value.tags.includes(newTag.value.trim())) {
    showAddTagInput.value = false
    return
  }
  
  const tag = newTag.value.trim()
  localDefect.value.tags.push(tag)
  newTag.value = ''
  showAddTagInput.value = false
  // 自动保存标签
  handleSaveField('tags')
}

const handleRemoveTag = (tag: string) => {
  if (!localDefect.value) return
  
  const index = localDefect.value.tags.indexOf(tag)
  if (index !== -1) {
    localDefect.value.tags.splice(index, 1)
    // 自动保存标签
    handleSaveField('tags')
  }
}
</script>

<style scoped lang="scss">
.defect-detail-dialog {
  :deep(.el-dialog) {
    max-height: 90vh;
    display: flex;
    flex-direction: column;
  }

  :deep(.el-dialog__body) {
    padding: 24px;
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  :deep(.el-dialog__header) {
    padding: 20px 24px;
    border-bottom: 1px solid #ebeef5;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  :deep(.el-dialog__title) {
    font-size: 18px;
    font-weight: 600;
    color: #303133;
  }

  :deep(.el-dialog__footer) {
    padding: 16px 24px;
    border-top: 1px solid #ebeef5;
    flex-shrink: 0;
  }
}

.defect-detail {
  display: flex;
  flex-direction: column;
  gap: 24px;
  height: 100%;
  min-height: 0;
}

.detail-header {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.header-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.detail-id {
  font-size: 13px;
  color: #909399;
  background: #f4f6fa;
  padding: 4px 10px;
  border-radius: 4px;
  font-weight: 500;
}

.status-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.title-section {
  margin-bottom: 8px;
}

.field-label {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 500;
  color: #606266;

  .required {
    color: #f56c6c;
  }
}

.title-input {
  width: 100%;
}

.field-error {
  :deep(.el-input__wrapper) {
    border-color: #f56c6c;
  }
}

.error-message {
  color: #f56c6c;
  font-size: 12px;
  margin-top: 4px;
}

.field-hint {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.4;
}

.select-prefix-avatar {
  margin-right: 8px;
  flex-shrink: 0;
}

.header-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 13px;
  color: #606266;
  align-items: center;
  
  .meta-user-item {
    display: flex;
    align-items: center;
    gap: 6px;
    
    .meta-label {
      white-space: nowrap;
    }
  }
  line-height: 1.8;

  span {
    white-space: nowrap;
  }

  .project-info,
  .requirement-info,
  .verifier-info {
    color: #409eff;
  }
}

.detail-body {
  display: flex;
  gap: 24px;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  align-items: flex-start;
}

.primary-column {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 0;
  overflow: hidden;
}

.side-column {
  width: 400px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 24px;
  position: sticky;
  top: 0;
  align-self: flex-start;
  gap: 16px;

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;
  }

  &::-webkit-scrollbar-thumb:hover {
    background: #a8a8a8;
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
  }
}

.section-card {
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 12px;
  padding: 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 4px 12px rgba(31, 56, 88, 0.05);
}

// 合并后的内容区域
.content-section {
  padding: 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.content-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid #ebeef5;
}

.content-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.content-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.content-scrollable {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  min-height: 0;

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;

    &:hover {
      background: #a8a8a8;
    }
  }

  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
  }
}

.content-editor {
  width: 100%;
}

.content-display {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.content-display-item {
  display: flex;
  flex-direction: column;
  gap: 12px;

  &:not(:last-child) {
    padding-bottom: 24px;
    border-bottom: 1px solid #ebeef5;
  }
}

.content-display-label {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 8px;
}

.content-empty {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
  padding: 40px 0;
}

.description-section {
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;

  .section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 20px 24px;
    border-bottom: 1px solid #ebeef5;
  }

  .section-title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
  }

  .section-actions {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .description-content {
    padding: 24px;
  }
}

.tabs-card {
  padding: 0;
  overflow: hidden;

  :deep(.el-tabs__header) {
    margin: 0;
    padding: 0 24px;
    border-bottom: 1px solid #ebeef5;
  }

  :deep(.el-tabs__content) {
    padding: 24px;
    flex: 1;
    overflow-y: auto;
    min-height: 0;
  }

  :deep(.el-tab-pane) {
    height: 100%;
  }
}

.content-tabs {
  height: 100%;
  display: flex;
  flex-direction: column;

  :deep(.el-tabs__content) {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
  }
}

.tab-content-wrapper {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
}

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.section-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.section-content {
  font-size: 14px;
  color: #606266;
  line-height: 1.7;
  display: flex;
  flex-direction: column;
  min-height: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.tab-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
  overflow-y: auto;
}

.other-section {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid #ebeef5;
}

.other-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 12px;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.info-card {
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 12px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 4px 12px rgba(31, 56, 88, 0.05);
}

.info-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.info-card-title {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
}

.info-form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.info-label {
  color: #909399;
  font-size: 13px;
}

.required {
  color: #f56c6c;
  margin-left: 4px;
}

// 编辑状态下的输入框样式
.editing-content {
  :deep(.el-textarea__inner) {
    min-height: 200px;
    font-size: 14px;
    line-height: 1.7;
  }
}

// 文本内容样式
.text-content {
  min-height: 60px;
  padding: 12px;
  background: #f5f7fa;
  border-radius: 8px;
  color: #606266;
  line-height: 1.7;
  white-space: pre-wrap;
  word-wrap: break-word;

  &:empty::before {
    content: '暂无内容';
    color: #909399;
  }
}

// 其他信息区域样式
.other-info {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.other-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;

  &:last-child {
    border-bottom: none;
  }
}

.other-label {
  font-size: 13px;
  color: #909399;
  font-weight: 500;
}

.other-value {
  font-size: 13px;
  color: #606266;
  text-align: right;
}

// 空状态样式
.empty-content {
  color: #909399;
  font-size: 14px;
  padding: 20px;
  text-align: center;
  background: #f5f7fa;
  border-radius: 8px;
}


// 详情标签页样式优化
.detail-tabs {
  height: 100%;
  display: flex;
  flex-direction: column;

  :deep(.el-tabs__header) {
    margin: 0;
    padding: 0 24px;
    border-bottom: 1px solid #ebeef5;
  }

  :deep(.el-tabs__content) {
    padding: 24px;
    flex: 1;
    overflow-y: auto;
    min-height: 0;
  }

  :deep(.el-tab-pane) {
    height: 100%;
  }
}

// 响应式设计
@media (max-width: 992px) {
  .detail-body {
    flex-direction: column;
  }

  .side-column {
    width: 100%;
    border-left: none;
    border-top: 1px solid #ebeef5;
    padding-left: 0;
    padding-top: 16px;
  }
}
</style>